home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / intrvews / xgrab.lha / xgrab / ui / textedit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-24  |  9.6 KB  |  476 lines

  1. /**
  2.    GRAB Graph Layout and Browser System
  3.  
  4.    Copyright (c) 1987, 1988, 1989 Stanford University
  5.    Copyright (c) 1989, Tera Computer Company
  6.  **/
  7.  
  8.   /**
  9.      Stolen from the InterViews 2.5 bin source files
  10.    **/
  11.  
  12. #include "ipaint.h"
  13. #include "istring.h"
  14. #include "liststring.h"
  15. #include "textedit.h"
  16. #include <InterViews/event.h>
  17. #include <InterViews/graphic.h>
  18. #include <InterViews/painter.h>
  19. #include <InterViews/shape.h>
  20. #include <InterViews/world.h>
  21. #include <stdio.h>
  22.  
  23. // Define constants.
  24.  
  25. static const Coord ENDCOL    = 10000; // gets us to actual end of most lines
  26. static const int SPACING    = 4;     // gives amount by which to tab
  27.  
  28. // Create bindings between keystrokes and editing commands.
  29.  
  30. static const char BEGLINE    = '\001'; // ^A
  31. static const char DELLINE    = '\013'; // ^K
  32. static const char DELNEXTCHAR    = '\004'; // ^D
  33. static const char DELPREVCHAR1    = '\010'; // ^H
  34. static const char DELPREVCHAR2    = '\177'; // DEL
  35. static const char DELREST    = '\032'; // ^Z
  36. static const char ENDLINE    = '\005'; // ^E
  37. static const char INDENT    = '\027'; // ^W
  38. static const char NEWLINE    = '\015'; // RET
  39. static const char NEXTCHAR    = '\006'; // ^F
  40. static const char NEXTLINE    = '\016'; // ^N
  41. static const char OPENLINE    = '\017'; // ^O
  42. static const char PREVCHAR    = '\002'; // ^B
  43. static const char PREVLINE    = '\020'; // ^P
  44. static const char TAB        = '\011'; // TAB
  45. static const char TOGGLEOW    = '\024'; // ^T
  46. static const char UNINDENT    = '\021'; // ^Q
  47.  
  48. // TextEdit sets itself up to begin editing a buffer initialized with
  49. // some text if there's any (stringlist == nil is okay).
  50.  
  51. TextEdit::TextEdit (StringList* stringlist, Graphic* out)
  52.     : (GraphicToPainter(out), NumCols(stringlist), NumLines(stringlist)) 
  53. {
  54.     caretstyle = Bar;
  55.     overwrite = false;
  56.     buffer = false;
  57.  
  58.     SetText(stringlist);
  59. }
  60.  
  61. // Handle inserts the TextEdit into the world, reads and processes
  62. // subsequent events until a DownEvent occurs, puts the DownEvent back
  63. // on the queue, and removes the TextEdit from the world.  Thus the
  64. // user can terminate typing text by clicking the mouse in the
  65. // TextEdit or selecting another tool or pulling down a menu.
  66.  
  67. void TextEdit::Handle (Event& e) 
  68. {
  69.     Interactor* underlying = e.target;
  70.     Coord l, b, r, t;
  71.     l = e.x;
  72.     t = e.y;
  73.     underlying->Align(BottomRight, 0, 0, r, b);
  74.     underlying->GetRelative(l, b);
  75.     underlying->GetRelative(r, t);
  76.     shape->width = min(shape->width, max(r - l, shape->hunits));
  77.     shape->height = min(shape->height, max(t - b, shape->vunits));
  78.     shape->height = (shape->height / shape->vunits) * shape->vunits;
  79.  
  80.     World* world;
  81.     e.GetAbsolute(world, e.x, e.y);
  82.     world->InsertPopup(this, l, t, TopLeft);
  83.     Read(e);
  84.  
  85.     while (e.eventType != DownEvent) 
  86.     {
  87.     if (e.eventType == KeyEvent && e.len > 0) 
  88.     {
  89.         HandleChar(e.keystring[0]);
  90.     }
  91.  
  92.     Read(e);
  93.     }
  94.  
  95.     if (e.target == this) 
  96.     {
  97.     GetRelative(e.x, e.y, underlying);
  98.     e.target = underlying;
  99.     }
  100.  
  101.     UnRead(e);
  102.     world->Remove(this);
  103. }
  104.  
  105. // GetText returns the buffer contents in a newly allocated list.
  106.  
  107. StringList* TextEdit::GetText () 
  108. {
  109.     StringList* stringlist = new StringList;
  110.  
  111.     for (TextLine* l = top; l != nil && l->text != nil; l = l->below) 
  112.     {
  113.     stringlist->Append(new StringNode(l->text, l->length));
  114.     }
  115.  
  116.     return stringlist;
  117. }
  118.  
  119. // SetText sets the initial contents of the text buffer.
  120.  
  121. void TextEdit::SetText (StringList* stringlist) 
  122. {
  123.     buffer = true;
  124.  
  125.     GoTo(1, 1);
  126.     EndText();
  127.  
  128.     if (stringlist != nil) 
  129.     {
  130.     if (stringlist->Size() > 0) 
  131.     {
  132.         String(stringlist->First()->GetString());
  133.     }
  134.  
  135.     for (stringlist->Next(); !stringlist->AtEnd(); stringlist->Next()) 
  136.     {
  137.         const char* string = stringlist->GetCur()->GetString();
  138.         NewLine();
  139.         String(string);
  140.     }
  141.     }
  142.  
  143.     GoTo(1, 1);
  144.     GetPos(line, column);
  145.     Caret();
  146.  
  147.     buffer = false;
  148.     Flush();
  149. }
  150.  
  151. // GraphicToPainter returns a Painter which will draw text like the
  152. // Graphic would have.
  153.  
  154. Painter* TextEdit::GraphicToPainter (Graphic* gs) 
  155. {
  156.     Painter* p = new Painter(stdpaint);
  157.  
  158.     PColor* fg = gs->GetFgColor();
  159.  
  160.     if (fg != nil) 
  161.     {
  162.     p->SetColors(*fg, p->GetBgColor());
  163.     }
  164.  
  165.     PColor* bg = gs->GetBgColor();
  166.  
  167.     if (bg != nil) 
  168.     {
  169.     p->SetColors(p->GetFgColor(), *bg);
  170.     }
  171.  
  172.     PFont* f = gs->GetFont();
  173.  
  174.     if (f != nil) 
  175.     {
  176.     p->SetFont(*f);
  177.     }
  178.  
  179.     return p;
  180. }
  181.  
  182. // NumCols returns the number of columns the text spans plus a default
  183. // additional number of columns.
  184.  
  185. int TextEdit::NumCols (StringList* stringlist) 
  186. {
  187.     int cols = 0;
  188.  
  189.     if (stringlist != nil) 
  190.     {
  191.     for (stringlist->First(); !stringlist->AtEnd(); stringlist->Next()) 
  192.     {
  193.         const char* string = stringlist->GetCur()->GetString();
  194.         cols = max(cols, strlen(string));
  195.     }
  196.     }
  197.  
  198.     return cols;
  199. }
  200.  
  201. // NumLines returns the number of lines in the text plus a default
  202. // additional number of rows.
  203.  
  204. int TextEdit::NumLines (StringList* stringlist) 
  205. {
  206.     int rows = 0;
  207.  
  208.     if (stringlist != nil) 
  209.     {
  210.     rows = stringlist->Size();
  211.     }
  212.  
  213.     return rows;
  214. }
  215.  
  216. // HandleChar carries out the editing command bound to the keystroke
  217. // if any.  Otherwise, it echoes the keystroke if it's a printing
  218. // character.
  219.  
  220. void TextEdit::HandleChar (char c) 
  221. {
  222.     switch (c) 
  223.     {
  224.         case BEGLINE:
  225.         begline();
  226.         break;
  227.         case DELLINE:
  228.         delline();
  229.         break;
  230.         case DELNEXTCHAR:
  231.         delnextchar();
  232.         break;
  233.         case DELPREVCHAR1:
  234.         case DELPREVCHAR2:
  235.         delprevchar();
  236.         break;
  237.         case DELREST:
  238.         delrest();
  239.         break;
  240.         case ENDLINE:
  241.         endline();
  242.         break;
  243.         case INDENT:
  244.         indent();
  245.         break;
  246.         case NEWLINE:
  247.         newline();
  248.         break;
  249.         case NEXTCHAR:
  250.         nextchar();
  251.         break;
  252.         case NEXTLINE:
  253.         nextline();
  254.         break;
  255.         case OPENLINE:
  256.         openline();
  257.         break;
  258.         case PREVCHAR:
  259.         prevchar();
  260.         break;
  261.         case PREVLINE:
  262.         prevline();
  263.         break;
  264.         case TAB:
  265.         tab();
  266.         break;
  267.         case TOGGLEOW:
  268.         toggleow();
  269.         break;
  270.         case UNINDENT:
  271.         unindent();
  272.         break;
  273.         default:
  274.         if (c >= ' ' && c <= '~') 
  275.         {
  276.             String(&c, 1);
  277.         }
  278.         break;
  279.     }
  280.  
  281.     GetPos(line, column);
  282.     Caret();
  283. }
  284.  
  285. // begline moves dot to the beginning of the current line.
  286.  
  287. void TextEdit::begline () 
  288. {
  289.     GoTo(line, 1);
  290. }
  291.  
  292. // delline deletes any text following dot on the current line.  If dot
  293. // was at the beginning or end of the line, delline joins the next
  294. // line to the current line.
  295.  
  296. void TextEdit::delline () 
  297. {
  298.     GoTo(line, ENDCOL);
  299.     GetPos(tline, tcolumn);
  300.     GoTo(line, column);
  301.  
  302.     if (tcolumn > column) 
  303.     {
  304.     Rubout(tcolumn - column);
  305.     }
  306.  
  307.     if (column == 1 || column == tcolumn) 
  308.     {
  309.     GoTo(line + 1, 1);
  310.     GetPos(tline, tcolumn);
  311.  
  312.     if (tline > line) 
  313.     {
  314.         Insert(-1, column - 1);
  315.     }
  316.  
  317.     GoTo(line, column);
  318.     }
  319. }
  320.  
  321. // delnextchar deletes the character after dot.  If dot was at the end
  322. // of the line, delnextchar joins the next line to the end of the
  323. // current line.
  324.  
  325. void TextEdit::delnextchar () 
  326. {
  327.     GoTo(line, ENDCOL);
  328.     GetPos(tline, tcolumn);
  329.  
  330.     if (column == tcolumn) 
  331.     {
  332.     GoTo(line + 1, 1);
  333.     GetPos(tline, tcolumn);
  334.  
  335.     if (tline > line) 
  336.     {
  337.         Insert(-1, column - 1);
  338.     }
  339.  
  340.     GoTo(line, column);
  341.     }
  342.     else 
  343.     {
  344.     GoTo(line, column);
  345.     Rubout(1);
  346.     }
  347. }
  348.  
  349. // delprevchar deletes the character before dot.  If dot was at the
  350. // beginning of the line, delprevchar joins the current line to the
  351. // previous line.
  352.  
  353. void TextEdit::delprevchar () 
  354. {
  355.     if (column > 1) 
  356.     {
  357.     GoTo(line, column - 1);
  358.     Rubout(1);
  359.     }
  360.     else 
  361.     {
  362.     prevchar();
  363.     GetPos(line, column);
  364.     Caret();
  365.     delnextchar();
  366.     }
  367. }
  368.  
  369. // delrest deletes any text following dot in the rest of the buffer.
  370.  
  371. void TextEdit::delrest () 
  372. {
  373.     EndText();
  374. }
  375.  
  376. // endline moves dot to the end of the current line.
  377.  
  378. void TextEdit::endline () 
  379. {
  380.     GoTo(line, ENDCOL);
  381. }
  382.  
  383. // indent adds count SPACING blanks to the current margin.
  384.  
  385. void TextEdit::indent () 
  386. {
  387.     Indent(SPACING);
  388. }
  389.  
  390. // newline moves dot to the beginning of the next line, opening a new
  391. // blank line and copying any text following dot if overwrite is false
  392. // or truncating the current line to dot if overwrite is true.
  393.  
  394. void TextEdit::newline () 
  395. {
  396.     NewLine();
  397. }
  398.  
  399. // nextchar moves dot after the next character.  If dot is at the end
  400. // of the current line, nextchar moves dot to the beginning of the
  401. // next line.
  402.  
  403. void TextEdit::nextchar () 
  404. {
  405.     GoTo(line, column + 1);
  406.     GetPos(tline, tcolumn);
  407.  
  408.     if (tcolumn == column) 
  409.     {
  410.     GoTo(line + 1, 1);
  411.     }
  412. }
  413.  
  414. // nextline moves dot to the same column in the next line or the end
  415. // of the next line, whichever is smaller.
  416.  
  417. void TextEdit::nextline () 
  418. {
  419.     GoTo(line + 1, column);
  420. }
  421.  
  422. // openline inserts a new blank line following the current line.
  423.  
  424. void TextEdit::openline () 
  425. {
  426.     Insert(1, -column);
  427.     GoTo(line, column);
  428. }
  429.  
  430. // prevchar moves dot before the previous character.  If dot is at the
  431. // beginning of the current line, prevchar moves dot to the end of the
  432. // previous line.
  433.  
  434. void TextEdit::prevchar () 
  435. {
  436.     if (column > 1) 
  437.     {
  438.     GoTo(line, column - 1); 
  439.     }
  440.     else 
  441.     {
  442.     GoTo(line - 1, ENDCOL);
  443.     }
  444. }
  445.  
  446. // prevline moves dot to the same column in the previous line or the
  447. // end of the previous line, whichever is smaller.
  448.  
  449. void TextEdit::prevline () 
  450. {
  451.     GoTo(line - 1, column);
  452. }
  453.  
  454. // tab inserts space characters up to the next multiple of SPACING.
  455.  
  456. void TextEdit::tab () 
  457. {
  458.     Tab(SPACING);
  459. }
  460.  
  461. // toggleow toggles overwrite which determines whether new characters
  462. // will replace existing text or existing text will move to the right
  463. // to make room.
  464.  
  465. void TextEdit::toggleow () 
  466. {
  467.     overwrite = !overwrite;
  468. }
  469.  
  470. // unindent removes count SPACING blanks from the current margin.
  471.  
  472. void TextEdit::unindent () 
  473. {
  474.     Indent(-SPACING);
  475. }
  476.